;
(function () {
    // 工具类名
    TempoMineMetaUtils = {};
    TempoMineMetaUtils.PREDICTION_COLUMN_NAME = 'prediction';
    TempoMineMetaUtils.PROB_COLUMN_NAME = 'probability';
    /**
     * 示例方法
     */
    TempoMineMetaUtils.methodA = function () {
        console.log("this is an example")
    }
    /** 所有数值类型名称定义 */
    TempoMineMetaUtils.NUMBERTYPES = {
        INT: "INT",
        FLOAT: "FLOAT",
        DOUBLE: "DOUBLE",
        LONG: "LONG"
    }

    /** 所有数值类型名称定义数组 */
    TempoMineMetaUtils.NUMBERTYPES_ARRAY = [
        TempoMineMetaUtils.NUMBERTYPES.INT,
        TempoMineMetaUtils.NUMBERTYPES.FLOAT,
        TempoMineMetaUtils.NUMBERTYPES.DOUBLE,
        TempoMineMetaUtils.NUMBERTYPES.LONG
    ]

    /**
     * 整个系统的数据类型定义
     * DATETIME:为时间戳类型，只在关系数据库输出使用
     */
    TempoMineMetaUtils.DATATYPES = {
        TIMESTAMP: "TIMESTAMP",
        STRING: "STRING",
        INT: TempoMineMetaUtils.NUMBERTYPES.INT,
        FLOAT: TempoMineMetaUtils.NUMBERTYPES.FLOAT,
        DOUBLE: TempoMineMetaUtils.NUMBERTYPES.DOUBLE,
        LONG: TempoMineMetaUtils.NUMBERTYPES.LONG,
        TEXT: "TEXT",
        TEMPO_VECTOR: "TEMPO_VECTOR",
        DATETIME: "DATETIME",
        ARRAY: "ARRAY",
        DATE: "DATE"
    }

    /**
     * 整个系统的数据类型定义（汉字对应英文）
     */
    TempoMineMetaUtils.DATATYPESChinaWithEng = {
        "日期型": "TIMESTAMP",
        "字符型": "STRING",
        "数值型(INT)": TempoMineMetaUtils.NUMBERTYPES.INT,
        "数值型(FLOAT)": TempoMineMetaUtils.NUMBERTYPES.FLOAT,
        "数值型(DOUBLE)": TempoMineMetaUtils.NUMBERTYPES.DOUBLE,
        "数值型(LONG)": TempoMineMetaUtils.NUMBERTYPES.LONG,
        "文本型": "TEXT",
        "向量": "TEMPO_VECTOR",
        "日期时间": "DATETIME",
        "数组": "ARRAY",
    }

    /**
     * 整个系统的数据类型定义（只包含数值型和日期型或日期时间）
     */
    TempoMineMetaUtils.DATATYPESONLYNUMORTIME = [
        "TIMESTAMP",
        TempoMineMetaUtils.NUMBERTYPES.INT,
        TempoMineMetaUtils.NUMBERTYPES.FLOAT,
        TempoMineMetaUtils.NUMBERTYPES.DOUBLE,
        TempoMineMetaUtils.NUMBERTYPES.LONG,
        "DATETIME",
        "DATE"
    ]

    /**
     * 判断当前字段类型是否为数值型
     *
     * @param type
     *            字段类型
     */
    TempoMineMetaUtils.isNumber = function (type) {
        return TempoMineMetaUtils.NUMBERTYPES.hasOwnProperty(type);
    }
    /**
     * 判断当前字段类型是否为字符型
     *
     * @param type
     *            字段类型
     */
    TempoMineMetaUtils.isString = function (type) {
        return TempoMineMetaUtils.DATATYPES.STRING == type || TempoMineMetaUtils.DATATYPES.TEXT == type;
    }
    /**
     * 判断当前字段类型是否为时间类型
     *
     * @param type
     *            字段类型
     */
    TempoMineMetaUtils.isDateTime = function (type) {
        return TempoMineMetaUtils.DATATYPES.TIMESTAMP == type || TempoMineMetaUtils.DATATYPES.DATETIME == type || TempoMineMetaUtils.DATATYPES.DATE == type;
    }
    /**
     * 判断两个类型是否是同一类（字符，数值，时间）
     *
     * @param type1
     *            字段类型
     * @param type2
     *            字段类型
     */
    TempoMineMetaUtils.isSameType = function (type1, type2) {
        return (TempoMineMetaUtils.isNumber(type1) && TempoMineMetaUtils.isNumber(type2))
            || (TempoMineMetaUtils.isString(type1) && TempoMineMetaUtils.isString(type2))
            || (TempoMineMetaUtils.isDateTime(type1) && TempoMineMetaUtils.isDateTime(type2));
    }
    /**
     * 判断当前属性是否为字符型
     *
     * @param type
     *            字段类型
     */
    TempoMineMetaUtils.isChar = function (type) {
        return TempoMineMetaUtils.DATATYPES.STRING == type;
    }

    /**
     * 判断当前属性是否为文本型,文本类型当字符型处理
     *
     * @param type
     *            字段类型
     */
    TempoMineMetaUtils.isText = function (type) {
        return TempoMineMetaUtils.DATATYPES.TEXT == type;
    }

    /**
     * 判断当前属性是否为日期型
     *
     * @param type
     *            字段类型
     */
    TempoMineMetaUtils.isTime = function (type) {
        return TempoMineMetaUtils.DATATYPES.TIMESTAMP == type;
    }

    /**
     * 判断当前属性是否为向量型,文本挖掘生成该类型
     *
     * @param type
     *            字段类型
     */
    TempoMineMetaUtils.isVector = function (type) {
        return TempoMineMetaUtils.DATATYPES.TEMPO_VECTOR == type;
    }
    /**
     * 判断当前字段类型是否是整型
     *
     * @param type  字段类型
     * @returns {boolean}
     */
    TempoMineMetaUtils.isInteger = function (type) {
        return TempoMineMetaUtils.DATATYPES.INT == type || TempoMineMetaUtils.DATATYPES.LONG == type;
    }
    /**
     * 判断当前字段类型是否是日期型or日期时间
     *
     * @param type
     * @returns {boolean}
     */
    TempoMineMetaUtils.isTimeType = function (type) {
        return TempoMineMetaUtils.DATATYPES.TIMESTAMP == type || TempoMineMetaUtils.DATATYPES.DATETIME == type;
    }
    /**
    /**
     * 进行已加载元信息和用户已选择元信息中的列名称和类型的比对，返回比对结果<br>
     * 1.如果用户已选择元信息中包含已加载中没有的列信息，则返回该列的具体对象列表和比对错误原因<br>
     * 返回的数组中对象的结构1： {"meta":choosedMetaI,"reason":"name"} 已选择列在待选项中未发现。<br>
     * 返回的数组中对象的结构2：{"meta":choosedMetaI,"reason":"type"} 已选择列的类型和待选项中不匹配。
     * 返回的数组中对象的结构2：{"meta":choosedMetaI,"reason":"more"} 待选项数据增加。
     *
     * @param preparedMeta:流程中传递的meta对象,该对象为一个数组，数组对象中必须包含
     *            name和type属性 <br>
     * @param choosedMeta
     *            :已选择的meta对象,该对象为一个数组，数组对象中必须包含 name和type属性<br>
     * @param returnObjType
     *            需要返回的错误对象集合的类型"array"：数组，"map"：代表map结构。默认值:"array"<br>
     *            如果返回为map，则key为name属性。
     * @param needValidLengthSame
     *           是否需要校验传入的两个数组的长度相同，默认不校验
     */
    TempoMineMetaUtils.checkMeta = function (preparedMeta, choosedMeta, returnObjType, needValidLengthSame) {
        var rTypeArray = "array";
        var rTypeMap = "map";
        // 设置返回类型的默认值
        if (!returnObjType) {
            returnObjType = rTypeArray;
        }
        // 参数检查
        if (!(returnObjType == rTypeArray || returnObjType == rTypeMap)) {
            console.log("TempoMineMetaUtils.checkMeta: param returnObjType value error!Must be \"" + rTypeArray + "\" or \"" + rTypeMap + "\"");
        }

        var rErrorMetas = [];
        if (returnObjType == rTypeMap) {
            rErrorMetas = TempoMineUtils.hashMap();
        }
        if (!choosedMeta) {
            console.log("TempoMineMetaUtils.checkMeta->choosedMeta is :"
                + choosedMeta);
            return rErrorMetas;
        }
        if (!preparedMeta) {
            console.log("TempoMineMetaUtils.checkMeta->preparedMeta is :"
                + preparedMeta);
            return rErrorMetas;
        }
        // 长度不一致
        if (needValidLengthSame && preparedMeta.length != choosedMeta.length) {
            var errorObj = {
                "meta": [],
                "reason": "more"
            }
            if (returnObjType == rTypeArray) {
                rErrorMetas.push(errorObj);
            } else {
                rErrorMetas.put("", errorObj);
            }
            return rErrorMetas;
        }
        var preparedMetaMap = TempoMineUtils.hashMap();
        for (var i = 0; i < preparedMeta.length; i++) {
            var meta = preparedMeta[i];
            var metaObj = TempoMineMetaUtils.convertMetaToObj(meta);
            preparedMetaMap.put(metaObj.desc/* + metaObj.name*/ + metaObj.type, metaObj);
        }


        for (var i = 0; i < choosedMeta.length; i++) {
            var choosedMetaI = choosedMeta[i];
            var keyN = choosedMetaI.desc/* + choosedMetaI.name*/ + choosedMetaI.type;
            var cmType = choosedMetaI.type;
            var preparedMeata = preparedMetaMap.get(keyN);
            var errorMetaObj = {// 默认是名称错误
                "meta": choosedMetaI,
                "reason": "name"
            };
            if (preparedMeata) {
                var isTypeEqual = TempoMineMetaUtils.typeEquals(cmType, preparedMeata.type);
                if (!isTypeEqual) {
                    errorMetaObj.reason = "type"
                }
                ;
                var isNameEqual = TempoMineMetaUtils.nameEquals(preparedMeata.desc, choosedMetaI.desc);
                if (!isNameEqual) {
                    if (returnObjType == rTypeArray) {
                        rErrorMetas.push(errorMetaObj);
                    } else {
                        rErrorMetas.put(errorMetaObj.meta.desc, errorMetaObj);
                    }
                }
                ;
            }
            if (!preparedMeata || errorMetaObj.reason == "type") {
                if (returnObjType == rTypeArray) {
                    rErrorMetas.push(errorMetaObj);
                } else {
                    rErrorMetas.put(errorMetaObj.meta.desc, errorMetaObj);
                }
            }
        }
        return rErrorMetas;
    }

    /**
     * 使用字段名注释名和类型组合校验字段是否发生改变。
     * @param preparedMeta
     * @param choosedMeta
     * @param returnObjType
     * @param needValidLengthSame
     * @returns {Array}
     */
    TempoMineMetaUtils.checkMetaContainName = function (preparedMeta, choosedMeta, returnObjType, needValidLengthSame) {
        var rTypeArray = "array";
        var rTypeMap = "map";
        // 设置返回类型的默认值
        if (!returnObjType) {
            returnObjType = rTypeArray;
        }
        // 参数检查
        if (!(returnObjType == rTypeArray || returnObjType == rTypeMap)) {
            console.log("TempoMineMetaUtils.checkMeta: param returnObjType value error!Must be \"" + rTypeArray + "\" or \"" + rTypeMap + "\"");
        }

        var rErrorMetas = [];
        if (returnObjType == rTypeMap) {
            rErrorMetas = TempoMineUtils.hashMap();
        }
        if (!choosedMeta) {
            console.log("TempoMineMetaUtils.checkMeta->choosedMeta is :"
                + choosedMeta);
            return rErrorMetas;
        }
        if (!preparedMeta) {
            console.log("TempoMineMetaUtils.checkMeta->preparedMeta is :"
                + preparedMeta);
            return rErrorMetas;
        }
        // 长度不一致
        if (needValidLengthSame && preparedMeta.length != choosedMeta.length) {
            var errorObj = {
                "meta": [],
                "reason": "more"
            }
            if (returnObjType == rTypeArray) {
                rErrorMetas.push(errorObj);
            } else {
                rErrorMetas.put("", errorObj);
            }
            return rErrorMetas;
        }
        var preparedMetaMap = TempoMineUtils.hashMap();
        for (var i = 0; i < preparedMeta.length; i++) {
            var meta = preparedMeta[i];
            var metaObj = TempoMineMetaUtils.convertMetaToObj(meta);
            preparedMetaMap.put(metaObj.desc + metaObj.name + metaObj.type, metaObj);
        }


        for (var i = 0; i < choosedMeta.length; i++) {
            var choosedMetaI = choosedMeta[i];
            var keyN = choosedMetaI.desc + choosedMetaI.name + choosedMetaI.type;
            var cmType = choosedMetaI.type;
            var preparedMeata = preparedMetaMap.get(keyN);
            var errorMetaObj = {// 默认是名称错误
                "meta": choosedMetaI,
                "reason": "name"
            };
            if (preparedMeata) {
                var isTypeEqual = TempoMineMetaUtils.typeEquals(cmType, preparedMeata.type);
                if (!isTypeEqual) {
                    errorMetaObj.reason = "type"
                }
                ;
                var isNameEqual = TempoMineMetaUtils.nameEquals(preparedMeata.desc, choosedMetaI.desc);
                if (!isNameEqual) {
                    if (returnObjType == rTypeArray) {
                        rErrorMetas.push(errorMetaObj);
                    } else {
                        rErrorMetas.put(errorMetaObj.meta.desc, errorMetaObj);
                    }
                }
                ;
            }
            if (!preparedMeata || errorMetaObj.reason == "type") {
                if (returnObjType == rTypeArray) {
                    rErrorMetas.push(errorMetaObj);
                } else {
                    rErrorMetas.put(errorMetaObj.meta.desc, errorMetaObj);
                }
            }
        }
        return rErrorMetas;
    }

    /**
     * 比对类型是否相同<br>
     * 只要两边是数值、两边是字符型或两边是日期时间型都认为相等。<br>
     * leftType 左值<br>
     * rightType 右值<br>
     * */
    TempoMineMetaUtils.typeEquals = function (leftType, rightType) {
        if (!leftType || !rightType) {
            console.error("type undefined or null！leftType:" + leftType + ",rightType:" + rightType);
            return false;
        }
        if (leftType == rightType) {
            return true;
        }
        return false;
    }
    /**
     * 比对注释名是否相同<br>
     * 只要两边是数值、两边是字符型或两边是日期时间型都认为相等。<br>
     * leftType 左值<br>
     * rightType 右值<br>
     * */
    TempoMineMetaUtils.nameEquals = function (leftName, rightName) {
        if (!leftName || !rightName) {
            console.error("type undefined or null！leftType:" + leftName + ",rightType:" + rightName);
            return false;
        }
        if (leftName == rightName) {
            return true;
        }
        return false;
    }
    /**
     * 提取数据源列信息被改变的用户提示信息
     *
     * @param rErrorMetas
     *            checkMeta方法返回的错误元信息
     */
    TempoMineMetaUtils.constructMetaChangeErrorInfo = function (errorInfoList) {
        var showMessage = TempoUtils.locale("mine.meta_error_metachanged");
        var typeChanges = [];
        var columnNotFoundInMeta = [];
        for (var i = 0; i < errorInfoList.length; i++) {
            var errInfo = errorInfoList[i];
            if (errInfo.reason == "type") {
                typeChanges.push(errInfo.meta.desc);
            } else if (errInfo.reason == "name") {
                columnNotFoundInMeta.push(errInfo.meta.desc);
            }
        }
        if (typeChanges.length > 0) {
            //类型改变的有：
            var typeChangesStr = TempoUtils
                    .locale("mine.meta_error_typechangedcolumns")
                + typeChanges.join(", ")
            showMessage += typeChangesStr + ";";
        }
        if (columnNotFoundInMeta.length > 0) {
            //字段不存在的有：
            columnNotFoundInMeta = TempoUtils
                    .locale("mine.meta_error_notexistscolumns")
                + columnNotFoundInMeta.join(", ") + typeChanges.join(", ");
            showMessage += columnNotFoundInMeta + ".";
        }
        return showMessage;
    }
    /**
     * 提取字段类型被改变的提示信息
     */
    TempoMineMetaUtils.getTypeChangedTip = function () {
        return TempoUtils.locale("mine.meta_field_type_changed_tip");
    }
    /**
     * 提取字段不存在的提示信息
     */
    TempoMineMetaUtils.getFieldNotExistsTip = function () {
        return TempoUtils.locale("mine.meta_field_not_exists_tip");
    }
    /**
     * 检查上下文的meta和用户已选择meta的元信息的差异。<br>
     * isError:为true时代表检测出错误，错误信息在errorInfo中存储
     * needValidLengthSame：是否需要校验传入的contextMeta与choosedMeta的长度相同，默认不校验
     * @return { isError : true, errorInfo : errorInfo };
     */
    TempoMineMetaUtils.checkMetaAndReturnInfo = function (contextMeta,
                                                          choosedMeta, needValidLengthSame) {
        var errorInfoList = TempoMineMetaUtils.checkMeta(contextMeta,
            choosedMeta, undefined, needValidLengthSame);
        if (!contextMeta || contextMeta.length == 0) {
            return {
                isError: true,
                errorInfo: TempoUtils.locale("mine.node_dataInput_error")
            };
        }
        if (errorInfoList.length && errorInfoList.length > 0) {
            var errorInfo = TempoMineMetaUtils
                .constructMetaChangeErrorInfo(errorInfoList);
            return {
                isError: true,
                errorInfo: errorInfo.length > 500 ? errorInfo.substring(0,500) + "..." : errorInfo
            };
        }
        return {
            isError: false,
            errorInfo: ""
        };
    }

    /**
     * 校验前后字段是否发生变化，通过字段+注释+类型三重校验
     * @param contextMeta
     * @param choosedMeta
     * @param needValidLengthSame
     * @returns {{isError: boolean, errorInfo: string}|{isError: boolean, errorInfo: *}}
     */
    TempoMineMetaUtils.checkMetaAndReturnInfoContainName = function (contextMeta,
                                                          choosedMeta, needValidLengthSame) {
        var errorInfoList = TempoMineMetaUtils.checkMetaContainName(contextMeta,
            choosedMeta, undefined, needValidLengthSame);
        if (!contextMeta || contextMeta.length == 0) {
            return {
                isError: true,
                errorInfo: TempoUtils.locale("mine.node_dataInput_error")
            };
        }
        if (errorInfoList.length && errorInfoList.length > 0) {
            var errorInfo = TempoMineMetaUtils
                .constructMetaChangeErrorInfo(errorInfoList);
            return {
                isError: true,
                errorInfo: errorInfo.length > 500 ? errorInfo.substring(0,500) + "..." : errorInfo
            };
        }
        return {
            isError: false,
            errorInfo: ""
        };
    }

    /**
     * 根据meta源信息，返回对应类型的数组
     * @param gridData
     * @returns {{types: [], descs: [], names: []}|{types: *, descs: *, names: *}}
     */
    TempoMineMetaUtils.getChoosedDatas = function (gridData) {
        if (!gridData) {
            return {"names": [], "types": [], "descs": []};
        }
        var names = [];
        var types = [];
        var descs = [];
        for (var key in gridData) {
            var rowData = gridData[key];
            // 如果前面连接关系数据库输入，rowDataLen有值，否则没有值
            var rowDataLen = rowData.length;
            // 如果前面连接关系数据库输入， rowData是一个数据
            if (rowDataLen) {
                for (var i = 0; i < rowDataLen; i++) {
                    names.push(rowData[i].name);
                    types.push(rowData[i].type);
                    descs.push(rowData[i].desc)
                }
                // 如果前面没有连接关系数据库输入，rowData是一个对象
            } else {
                names.push(rowData.name);
                types.push(rowData.type);
                descs.push(rowData.desc)
            }
        }
        return {"names": names, "types": types, "descs": descs};
    }

    /**
     * 校验当前元信息与上一次保存的元信息是否完全相同
     */
    TempoMineMetaUtils.checkMetaAndPreMeta = function (contextMeta,
                                                       preMetadata, needValidLengthSame) {
        var preMetadataObj = [];
        if (!preMetadata) {
            preMetadata = [];
        }
        for (var i = 0; i < preMetadata.length; i++) {
            preMetadataObj.push(TempoMineMetaUtils.convertMetaToObj(preMetadata[i]));
        }
        return TempoMineMetaUtils.checkMetaAndReturnInfo(contextMeta, preMetadataObj, needValidLengthSame);
    }

    /**
     * 校验当前元信息与上一次保存的元信息是否完全相同
     *
     * @param contextMeta 新数据
     * @param preMetadata 旧数据
     * @param needValidLengthSame
     * @returns {{isError: boolean, errorInfo: string}|{isError: boolean, errorInfo: *}}
     */
    TempoMineMetaUtils.checkMetaAndPreMetaContainName = function (contextMeta,
                                                                  preMetadata, needValidLengthSame) {
        var preMetadataObj = [];
        if (!preMetadata) {
            preMetadata = [];
        }
        for (var i = 0; i < preMetadata.length; i++) {
            preMetadataObj.push(TempoMineMetaUtils.convertMetaToObj(preMetadata[i]));
        }
        return TempoMineMetaUtils.checkMetaAndReturnInfoContainName(contextMeta, preMetadataObj, needValidLengthSame);
    }

    /**
     * 将metadata中的第0项设置为返回对象的desc属性值<br>
     * 第1项设置为name<br>
     * 第2项设置为type <br>
     * 第3个值设置为role<br>
     */
    TempoMineMetaUtils.convertMetaToObj = function (metadata) {
        if (metadata) {
            // var obj = {};
            // 字段名
            // obj.desc = metadata[0];
            // 名称
            // obj.name = metadata[1];
            // 类型
            // obj.type = metadata[2];
            // 角色
            // obj.role = metadata[3];
            return {desc: metadata[0], name: metadata[1],  role: metadata[3],type: metadata[2]};
            // return obj;
        } else {
            return {};
        }
    }

    /**
     * 将metadata中的第0项设置为返回对象的desc属性值<br>
     * 第1项设置为name<br>
     * 第2项设置为type <br>
     * 第3个值设置为role<br>
     * 第4个值设置为role<br>
     */
    TempoMineMetaUtils.convertMetaToObjComment = function (metadata) {
        if (metadata == null) {
            return null;
        }
        var metadataClone = TempoUtils.clone(metadata)
        if (metadataClone) {
            if (metadataClone[4] == undefined) {
                metadataClone[4] = false;
            }
            return {desc: metadataClone[0], name: metadataClone[1], type: metadataClone[2], role: metadataClone[3], ifShowCommentName: metadataClone[4]};
        } else {
            return {};
        }
    }

    /**
     * 将字段转化为数组对象
     */
    TempoMineMetaUtils.convertMetaToObjOne = function (metadata) {
        if (metadata && metadata.length >= 4) {
            // 字段名
            var name = metadata[0];
            // 名称
            var label = metadata[1];
            // 类型
            var type = metadata[2];
            // 角色
            var role = metadata[3];
            // 是否展示元信息的别名
            var ifShowCommentName = false;
            if(metadata.length >= 5 ){
                ifShowCommentName = metadata[4];
            }
            return {name: name, label: label, type: type, role: role ,ifShowCommentName: ifShowCommentName};
        } else {
            return {};
        }
    }



    /**
     * 将字段对象转换为数组
     */
    TempoMineMetaUtils.convertObjToMeta = function (metaObj) {
        if (metaObj == null) {
            return null;
        }
        var metaArray = [];
        // 字段名
        metaArray.push(metaObj.desc);
        // 名称
        metaArray.push(metaObj.name);
        // 类型
        metaArray.push(metaObj.type);
        // 角色
        metaArray.push(metaObj.role);
        return metaArray;
    }

    /**
     * 将字段对象转换为数组 把name放在第一个
     */
    TempoMineMetaUtils.convertObjToMetaOne = function (metaObj) {
        if (metaObj == null) {
            return null;
        }
        var metaArray = [];
        // 名称
        metaArray.push(metaObj.name);
        // 字段名
        metaArray.push(metaObj.desc);
        // 类型
        metaArray.push(metaObj.type);
        // 角色
        metaArray.push(metaObj.role);
        return metaArray;
    }

    /**
     * 将字段对象转换为数组 泰康新增（ifShowCommentName）
     */
    TempoMineMetaUtils.convertObjToMetaComment = function (metaObj) {
        if (metaObj == null) {
            return null;
        }
        var metaArray = [];
        // 字段名
        metaArray.push(metaObj.name);
        // 名称
        metaArray.push(metaObj.desc);
        // 类型
        metaArray.push(metaObj.type);
        // 角色
        metaArray.push(metaObj.role);
        // 是否显示注释
        metaArray.push(metaObj.ifShowCommentName || false);
        return metaArray;
    }


    /**
     * 将元信息转化为Attribute数组对象
     * @param index
     * @param objectMetaArray
     */
    TempoMineMetaUtils.convertMetaToAttribute = function (index,objectMetaArray) {
        var objectMetaArray = TempoUtils.clone(objectMetaArray);
        // 将字段转化为数组对象
        var metaObjOne = TempoMineMetaUtils.convertMetaToObjOne(objectMetaArray);
        var attribute = {};
        // 判断解析结果是否为空
        if(!$.isEmptyObject(metaObjOne)){
            attribute = {
                extraAttributes: null,
                ifShowCommentName: metaObjOne.ifShowCommentName || false,
                index: index,
                label: metaObjOne.label,
                name: metaObjOne.name,
                outPutType: "DEFAULT",
                role: metaObjOne.role,
                tempoVectorMeta: null,
                type: metaObjOne.type,
            };
        }
        return attribute;
    };


    /**
     * 清除当前扩展编程节点输出端口在数据库中存储的元信息(70行)
     */
    TempoMineMetaUtils.cleanScriptNodeOutPortMeta = function(data){
        var scopes = data.scope.outScope;
        // 遍历所有输出端口，将该输出端口对应的数据库中存储的元信息进行清除。
        for (var i = 0; i < scopes.length; i++) {
            var sourceScope = scopes[i];
            var portCode = sourceScope.code;
            // 如果是模型输出端口，直接跳过
            if(portCode == "object"){
                continue;
            }
            // 将数据库中的元信息进行清除
            var id = data.eid + "_" + portCode;
            $.ajax({
                url: contextPath + '/api/ai/mineExecute/deleteNodeMetaInfo',
                async: false,
                data: {id: id},
                success: function (rs) {
                    //将元信息清空
                    console.log( portCode + "输出端口数据库元信息清除！")
                }
            });
        }
    };

    /**
     * 在用户已选择列表中，字段类型显示名称映射对象
     */
    TempoMineMetaUtils.getFieldTypeSelectValue = function (code) {
        var fTypeSelV = {};
        var types = TempoMineMetaUtils.DATATYPES;
        var i18nPrefix = "mine.meta_fields_label";
        var ns = "_number";
        fTypeSelV[types.STRING] = TempoUtils.locale(i18nPrefix + "_char");
        fTypeSelV[types.INT] = TempoUtils.locale(i18nPrefix + ns) + "(INT)";
        fTypeSelV[types.FLOAT] = TempoUtils.locale(i18nPrefix + ns) + "(FLOAT)";
        fTypeSelV[types.DOUBLE] = TempoUtils.locale(i18nPrefix + ns)
            + "(DOUBLE)";
        fTypeSelV[types.LONG] = TempoUtils.locale(i18nPrefix + ns) + "(LONG)";
        fTypeSelV[types.TIMESTAMP] = TempoUtils.locale(i18nPrefix
            + "_timestamp");
        fTypeSelV[types.DATETIME] = TempoUtils.locale(i18nPrefix
            + "_datetime");
        fTypeSelV[types.TEXT] = TempoUtils.locale(i18nPrefix
            + "_text");
        if ("object" != code) {
            fTypeSelV[types.TEMPO_VECTOR] = TempoUtils.locale(i18nPrefix
                + "_tempo_vector");
        }
        return fTypeSelV;
    }

    /**
     * 在用户已选择列表中，字段类型显示名称映射对象（只包含最基本的六大类）
     */
    TempoMineMetaUtils.getFieldTypeSelectValueBasicType = function () {
        var fTypeSelV = {};
        var types = TempoMineMetaUtils.DATATYPES;
        var i18nPrefix = "mine.meta_fields_label";
        var ns = "_number";
        fTypeSelV[types.STRING] = TempoUtils.locale(i18nPrefix + "_char");
        fTypeSelV[types.INT] = TempoUtils.locale(i18nPrefix + ns) + "(INT)";
        fTypeSelV[types.FLOAT] = TempoUtils.locale(i18nPrefix + ns) + "(FLOAT)";
        fTypeSelV[types.DOUBLE] = TempoUtils.locale(i18nPrefix + ns) + "(DOUBLE)";
        fTypeSelV[types.LONG] = TempoUtils.locale(i18nPrefix + ns) + "(LONG)";
        fTypeSelV[types.TIMESTAMP] = TempoUtils.locale(i18nPrefix + "_timestamp");
        return fTypeSelV;
    }

    /**
     * 在用户已选择列表中，字段类型显示名称映射对象（包含所有日期类型）
     */
    TempoMineMetaUtils.getFieldTypeSelectValueBasicTypeContainAllDate = function () {
        var fTypeSelV = {};
        var types = TempoMineMetaUtils.DATATYPES;
        var i18nPrefix = "mine.meta_fields_label";
        var ns = "_number";
        fTypeSelV[types.STRING] = TempoUtils.locale(i18nPrefix + "_char");
        fTypeSelV[types.INT] = TempoUtils.locale(i18nPrefix + ns) + "(INT)";
        fTypeSelV[types.FLOAT] = TempoUtils.locale(i18nPrefix + ns) + "(FLOAT)";
        fTypeSelV[types.DOUBLE] = TempoUtils.locale(i18nPrefix + ns) + "(DOUBLE)";
        fTypeSelV[types.LONG] = TempoUtils.locale(i18nPrefix + ns) + "(LONG)";
        fTypeSelV[types.TIMESTAMP] = TempoUtils.locale(i18nPrefix + "_timestamp");
        fTypeSelV[types.DATETIME] = TempoUtils.locale(i18nPrefix + "_timestamp");
        fTypeSelV[types.DATE] = TempoUtils.locale(i18nPrefix + "_timestamp");
        return fTypeSelV;
    }

    /**
     * 在用户已选择列表中，字段类型显示名称映射对象加数组并移除other中的
     * @param other 类型的编码数组或字符串  例：types.STRING
     */
    TempoMineMetaUtils.getFieldTypeSelectValueAndMoveOther = function (other) {
        var types = TempoMineMetaUtils.getFieldTypeSelectValue();
        if (typeof (other) != "string") {
            for (var i in other) {
                delete types[other[i]];
            }
        } else {
            delete types[other];
        }
        return types;
    }

    /**
     * 在用户已选择列表中，字段类型显示名称映射对象加数组
     */
    TempoMineMetaUtils.getFieldTypeSelectValueOne = function () {
        var fTypeSelV = {};
        var types = TempoMineMetaUtils.DATATYPES;
        var i18nPrefix = "mine.meta_fields_label";
        var ns = "_number";
        fTypeSelV[types.STRING] = TempoUtils.locale(i18nPrefix + "_char");
        fTypeSelV[types.INT] = TempoUtils.locale(i18nPrefix + ns) + "(INT)";
        fTypeSelV[types.FLOAT] = TempoUtils.locale(i18nPrefix + ns) + "(FLOAT)";
        fTypeSelV[types.DOUBLE] = TempoUtils.locale(i18nPrefix + ns)
            + "(DOUBLE)";
        fTypeSelV[types.LONG] = TempoUtils.locale(i18nPrefix + ns) + "(LONG)";
        fTypeSelV[types.TIMESTAMP] = TempoUtils.locale(i18nPrefix
            + "_timestamp");
        fTypeSelV[types.DATETIME] = TempoUtils.locale(i18nPrefix
            + "_datetime");
        fTypeSelV[types.TEXT] = TempoUtils.locale(i18nPrefix
            + "_text");
        fTypeSelV[types.TEMPO_VECTOR] = TempoUtils.locale(i18nPrefix
            + "_tempo_vector");
        fTypeSelV[types.ARRAY] = TempoUtils.locale(i18nPrefix
            + "_array") + "(ARRAY)";
        return fTypeSelV;
    }

    /**
     * 根据名称、类型和角色构建预测列Meta对象 检测列中是否重名，如果重名，则赘"1"
     * @param metas 上下文元信息列表
     * @param name  字段名，如果为空，则默认取TempoMineMetaUtils.PREDICTION_COLUMN_NAME
     * @param type  要生成元信息的类型
     * @param role  要生成元信息的角色
     * @param fieldName 字段名，如果为空，则默认取TempoMineMetaUtils.PREDICTION_COLUMN_NAME
     */
    TempoMineMetaUtils.checkPredictionAndReturnMeta = function (metas, name, type, role, fieldName) {
        // 一次遍历如果没有发现和TempoMineMetaUtils.PREDICTION_COLUMN_NAME重名，则直接返回
        var metaFieldNameMap = {};
        var preConst = TempoMineMetaUtils.PREDICTION_COLUMN_NAME;
        if (fieldName && fieldName.trim() != "") {
            preConst = fieldName;
        }

        if (!name) {
            name = TempoMineMetaUtils.PREDICTION_COLUMN_NAME;
        }
        if (!metas) {
            return {};
        }
        var isFirstIterConflictName = false;// 是否通过一次遍历检测出重名
        for (var i = 0; i < metas.length; i++) {
            var meta = TempoMineMetaUtils.convertMetaToObj(metas[i]);
            // 提取字段名
            var fieldName = meta.desc;
            metaFieldNameMap[fieldName] = meta;
            if (fieldName.toLowerCase() == preConst.toLowerCase()) {
                isFirstIterConflictName = true;
            }
        }

        // 如果一次遍历直接检测到重名，则返回一个元信息对象
        if (!isFirstIterConflictName) {

            return TempoMineMetaUtils.convertObjToMeta({
                "desc": preConst,
                "name": name, "type": type, "role": role
            });
        } else {
            // 最多检测100次
            var cCName = preConst + "1";
            for (var j = 0; j < 100; j++) {
                var conflictName = metaFieldNameMap[cCName];
                if (!conflictName) {
                    if (!name) {
                        name = cCName;
                    }
                    return TempoMineMetaUtils.convertObjToMeta(
                        {"desc": cCName, "name": cCName, "type": type, "role": role}
                    );
                }
                cCName = cCName + "1";
            }
            console.error("too much confilict name,max than 100!");
        }
    }

    /**
     * 根据名称、类型和角色构建预测列Meta对象 检测列中是否重名，如果重名，则赘"1"，还需要保存是否显示注释名
     * @param metas 上下文元信息列表
     * @param desc  字段名，如果为空，则默认取TempoMineMetaUtils.PREDICTION_COLUMN_NAME
     * @param type  要生成元信息的类型
     * @param role  要生成元信息的角色
     * @param name  注释名，如果为空，则默认取TempoMineMetaUtils.PREDICTION_COLUMN_NAME
     * @param ifShow  是否显示注释名
     */
    TempoMineMetaUtils.checkPredictionAndReturnMetaWithDesc = function (metas, desc, type, role, name, ifShow) {
        // 一次遍历如果没有发现和TempoMineMetaUtils.PREDICTION_COLUMN_NAME重名，则直接返回
        var metaFieldNameMap = {};
        var preConst = TempoMineMetaUtils.PREDICTION_COLUMN_NAME;
        if (desc && desc.trim() != "") {
            preConst = desc;
        }

        if (!name) {
            name = TempoMineMetaUtils.PREDICTION_COLUMN_NAME;
        }
        if (!metas) {
            return {};
        }
        var isFirstIterConflictName = false;// 是否通过一次遍历检测出重名
        for (var i = 0; i < metas.length; i++) {
            var meta = TempoMineMetaUtils.convertMetaToObj(metas[i]);
            // 提取字段名
            var fieldName = meta.desc;
            metaFieldNameMap[fieldName] = meta;
            if (fieldName.toLowerCase() == preConst.toLowerCase()) {
                isFirstIterConflictName = true;
            }
        }

        // 如果一次遍历直接检测到重名，则返回一个元信息对象
        if (!isFirstIterConflictName) {
            return TempoMineMetaUtils.convertObjToMetaComment({
                "name": preConst,
                "desc": name,
                "type": type,
                "role": role,
                "ifShowCommentName": ifShow,
            });
        } else {
            // 最多检测100次
            var cCName = preConst + "1";
            var cCDesc = name + "1";
            for (var j = 0; j < 100; j++) {
                var conflictName = metaFieldNameMap[cCName];
                if (!conflictName) {
                    if (!name) {
                        name = cCName;
                    }
                    return TempoMineMetaUtils.convertObjToMetaComment(
                        {"name": cCName, "desc": cCDesc, "type": type, "role": role, "ifShowCommentName": ifShow,}
                    );
                }
                cCName = cCName + "1";
                cCDesc = cCDesc + "1";
            }
            console.error("too much confilict name,max than 100!");
        }
    }

    /**
     * 根据名称、类型和角色构建预测列Meta对象 检测列中是否重名，如果重名，则赘"1"
     * @param metas 上下文元信息列表
     * @param name  字段名，如果为空，则默认取TempoMineMetaUtils.PREDICTION_COLUMN_NAME
     * @param type  要生成元信息的类型
     * @param role  要生成元信息的角色
     * @param fieldName 字段名，如果为空，则默认取TempoMineMetaUtils.PREDICTION_COLUMN_NAME
     */
    TempoMineMetaUtils.checkProbAndReturnMeta = function (metas, name, type, role, fieldName) {
        // 一次遍历如果没有发现和TempoMineMetaUtils.PREDICTION_COLUMN_NAME重名，则直接返回
        var metaFieldNameMap = {};
        var preConst = TempoMineMetaUtils.PROB_COLUMN_NAME;
        if (fieldName && fieldName.trim() != "") {
            preConst = fieldName;
        }

        if (!name) {
            name = TempoMineMetaUtils.PROB_COLUMN_NAME;
        }
        if (!metas) {
            return {};
        }
        var isFirstIterConflictName = false;// 是否通过一次遍历检测出重名
        for (var i = 0; i < metas.length; i++) {
            var meta = TempoMineMetaUtils.convertMetaToObj(metas[i]);
            // 提取字段名
            var fieldName = meta.desc;
            metaFieldNameMap[fieldName] = meta;
            if (fieldName.toLowerCase() == preConst.toLowerCase()) {
                isFirstIterConflictName = true;
            }
        }

        // 如果一次遍历直接检测到重名，则返回一个元信息对象
        if (!isFirstIterConflictName) {

            return TempoMineMetaUtils.convertObjToMeta({
                "desc": preConst,
                "name": name, "type": type, "role": role
            });
        } else {
            // 最多检测100次
            var cCName = preConst + "1";
            for (var j = 0; j < 100; j++) {
                var conflictName = metaFieldNameMap[cCName];
                if (!conflictName) {
                    if (!name) {
                        name = cCName;
                    }
                    return TempoMineMetaUtils.convertObjToMeta(
                        {"desc": cCName, "name": cCName, "type": type, "role": role}
                    );
                }
                cCName = cCName + "1";
            }
            console.error("too much confilict name,max than 100!");
        }
    }

    /**
     * 在上下文元信息中增加聚类算法的预测列
     * */
    TempoMineMetaUtils.addClusterPreditionColumn = function (config, meta) {

    }

    /**
     * 在上下文元信息中增加算法的预测列
     * */
    TempoMineMetaUtils.addPredictColumn = function (config, metaSource, isClassification) {
        var meta = TempoUtils.clone(metaSource);
        var name = TempoMineMetaUtils.PREDICTION_COLUMN_NAME;
        var role = window.mineConstant.ROLE_TYPE_REGULAR;
        var type = TempoMineMetaUtils.DATATYPES.STRING;
        if (config.category == 'classification' || config.id == 'autoclassification' || config.id == 'votingclassify' || (config.id == 'automl' && isClassification)) {
            type = TempoMineMetaUtils.DATATYPES.STRING;
        }
        if (config.category == 'clustering' || config.id == 'autoclustering') {
            type = TempoMineMetaUtils.DATATYPES.STRING;
        }
        if (config.category == 'regression' || config.id == 'autoreg' || config.id == 'votingreg' || config.id == 'regressiondnn' || config.id == 'lstm' || (config.id == 'automl' && !isClassification)) {
            type = TempoMineMetaUtils.DATATYPES.DOUBLE;
        }
        if (meta) {
            var metaAdded = TempoMineMetaUtils.checkPredictionAndReturnMeta(meta, null, type, role, name);
            meta.push(metaAdded);
        }

        if (isClassification) {
            var name = TempoMineMetaUtils.PROB_COLUMN_NAME;
            var role = window.mineConstant.ROLE_TYPE_REGULAR;
            var type = TempoMineMetaUtils.DATATYPES.TEMPO_VECTOR;
            var metaAdded = TempoMineMetaUtils.checkProbAndReturnMeta(meta, null, type, role, name);
            meta.push(metaAdded);
        }
        return meta;
    }

    TempoMineMetaUtils.validateScript2 = function (param, node, lang, script, trainData, callback, tryrun, tempUploadInfo, configParameters) {
        var metas = [];
        var widget = node.attr('_widgetname');
        var config = node[widget]('getData')
        var scope = config.scope;
        scope.inScope.forEach(function (p) {
            var meta = node[widget]('getMetaData', p.code, 'in', p.code);
            var pMeta = {};
            pMeta.code = p.code;
            pMeta.type = p.type;
            var mt = [];
            if (meta && Array.isArray(meta) && meta.length) {
                mt = meta.map(function (row) {
                    return TempoMineMetaUtils.convertMetaToObjComment(row);
                });
            }
            pMeta.meta = mt;
            metas.push(pMeta);
        })
        var pythonModelPath;
        var pythonModelReadNode = node[widget]('getPreviousNodeEleByCodeAndEid','object', config.eid);
        if(pythonModelReadNode && pythonModelReadNode != null){
            var readPythonModelData = pythonModelReadNode[pythonModelReadNode.attr("_widgetname")]("getData");
            if(readPythonModelData && readPythonModelData != null && "readpythonmodel" == readPythonModelData.nodeType ){
                var pythonParameters = readPythonModelData.parameters;
                if(pythonParameters.name && pythonParameters.name != null){
                    pythonModelPath = {
                        fileId:pythonParameters.fileId,
                        flowId:pythonParameters.flowId,
                        name:pythonParameters.name,
                        themeId:pythonParameters.themeId
                    }
                }
            }
        }
        var process = $("<div/>").tempoprogressbar();
        // var url = contextPath + '/api/ai/mine/script/validate'
        var url = contextPath + '/api/ai/node/script/validate';
        // 处理designModel为空的情况
        if (!configParameters) {
            configParameters = [];
        }
        var params = {
            params: JSON.stringify(param),
            lang: lang,
            content: JSON.stringify(metas),
            script: script,
            tryrun: tryrun,
            tempUploadInfo: JSON.stringify(trainData),
            configParameters: JSON.stringify(configParameters)
        };
        //获取当前流程的python资源限制cpu和内存
        var tryRunParams = TempoMineMetaUtils.getTryRunParams();
        //python编程节点校验需要传递资源限制参数
        if (lang == "python" || lang == "pythonparallelization") {
            params["tryRunParams"] = JSON.stringify(tryRunParams);
            if(pythonModelPath){
                params["pythonModelPath"]=JSON.stringify(pythonModelPath)
            }
        }
        TempoMineUtils.encodeParams(params);
        $.ajax({
            url: url,
            type: "post",
            data: params,
            success: function (data) {
                process.tempoprogressbar("destroy");
                if (data.data != null) {
                    callback(data.data);
                } else {
                    $("<div/>").alert({
                        msg: 'Error: ' + data.message,
                        width: '250px'
                    });
                }

            },
            error: function (xhr, textStatus, errorThrown) {
                process.tempoprogressbar("destroy");
                $("<div/>").alert({
                    msg: 'Error: ' + textStatus,
                    width: '250px'
                });
            },
            complete: function () {

            }
        });
    }

    /**
     * 获取当前流程的python资源限制cpu和内存
     * @returns {{limitExtendMemory: *, limitExtendCpu: *}}
     */
    TempoMineMetaUtils.getTryRunParams = function () {
        var analyseStatus = Eventbus.triggerHandler("getAnalyseStatus")[0];
        var id = analyseStatus.getMainId();
        var page = analyseStatus.getFlowPanel(id);
        var option = page.panel.flowpanel('getJson');
        //cpu
        var limitExtendCpu = option.runTimeConfig ? option.runTimeConfig.limitExtendCpu : "";
        //内存
        var limitExtendMemory = option.runTimeConfig ? option.runTimeConfig.limitExtendMemory : "";
        var tryRunParams = {
            "limitExtendCpu": limitExtendCpu,
            "limitExtendMemory": limitExtendMemory,
        }
        return tryRunParams;
    }

    /**
     * 添加参数是否模拟运行
     * @param tryrun
     * @date 2017年12月16日11:03:58
     *
     */
    TempoMineMetaUtils.validateScript = function (node, lang, script, trainData, callback, tryrun, tempUploadInfo) {
        this.validateScript2({}, node, lang, script, trainData, callback, tryrun, tempUploadInfo)
    }

    TempoMineMetaUtils.getActualSript = function (script, params) {
        if (!script || script.indexOf("$") == -1 || !params || params.length == 0) {
            return script;
        }

        var newParams = TempoUtils.clone(params);
        newParams = TempoMineUtils.convertDefaultParam(newParams);
        for (var i = 0; i < newParams.length; i++) {
            if (!newParams[i].paramName || newParams[i].paramValue == undefined) {
                continue;
            }
            var reg = new RegExp("\\$\\{" + newParams[i].paramName + "\\}", 'g');
            script = script.replace(reg, newParams[i].paramValue);
            // 替换完成后若不存在参数，则直接返回
            if (script.indexOf("$") == -1) {
                break;
            }
        }
        return script;
    }
    /**
     * 输出节点的支持转换的类型控制
     */
    TempoMineMetaUtils.outputTypeLimit = function (gridSelect, dataType, dbType) {
        var dTypes = TempoMineMetaUtils.DATATYPES;
        if (TempoMineMetaUtils.isNumber(dataType)) {
            gridSelect.find("option[value='" + dTypes.DATETIME + "']").remove();
            gridSelect.find("option[value='" + dTypes.TIMESTAMP + "']").remove();
        }
        if (TempoMineMetaUtils.isDateTime(dataType)) {
            gridSelect.find("option[value='INT']").remove();
            gridSelect.find("option[value='FLOAT']").remove();
            gridSelect.find("option[value='DOUBLE']").remove();
            gridSelect.find("option[value='LONG']").remove();
        }
        if (!TempoMineMetaUtils.isVector(dataType)) {
            gridSelect.find("option[value='" + dTypes.TEMPO_VECTOR + "']").remove();
        } else {
            gridSelect.find("option[value!='" + dTypes.TEMPO_VECTOR + "']").remove();
        }
        if (dbType) {
            switch (dbType) {
                case "hbase":
                    gridSelect.find("option[value!='" + dTypes.STRING + "']").remove();
                    break;
                case "es":
                    gridSelect.find("option[value='" + dTypes.DATETIME + "']").remove();
                    break;
                case "db2":
                    gridSelect.find("option[value='" + dTypes.DATETIME + "']").remove();
                    break;
                case "sqlserver":
                    gridSelect.find("option[value='" + dTypes.DATETIME + "']").remove();
                    break;
            }
        }
    }
    /**
     * 允许转换的类型校验 兼容历史，对历史节点进行报错提示
     */
    TempoMineMetaUtils.outputTypeLimitValidate = function (rowData, inType, outType, dbType) {
        var dTypes = TempoMineMetaUtils.DATATYPES;
        var sourceType = rowData[inType];
        var tagetType = rowData[outType];
        var numberBan = [dTypes.DATETIME, dTypes.TIMESTAMP, dTypes.TEMPO_VECTOR];
        var timeBan = [dTypes.INT, dTypes.FLOAT, dTypes.DOUBLE, dTypes.LONG, dTypes.TEMPO_VECTOR];
        var vectOnly = dTypes.TEMPO_VECTOR;
        if (TempoMineMetaUtils.isNumber(sourceType)) {
            if (numberBan.indexOf(tagetType) > -1) {
                return false;
            }
            return true;
        }
        //历史节点日期时间类型的 es，sqlserver等就不用再管了[跟需求确认了]
        if (TempoMineMetaUtils.isDateTime(sourceType)) {
            if (timeBan.indexOf(tagetType) > -1) {
                return false;
            }
            return true;
        }
        if (TempoMineMetaUtils.isVector(sourceType)) {
            if (vectOnly == tagetType) {
                return true;
            }
            return false;
        }
        if (TempoMineMetaUtils.isVector(tagetType)) {
            if (vectOnly == sourceType) {
                return true;
            }
            return false;
        }
        return true;
    }

    /**
     * 将元信息转换为下拉选择框的数据格式 metas:元信息 cache:缓存列，key值为字段名，value值为类型(该参数可传入，也可忽略)
     */
    TempoMineMetaUtils.convertMetaToSelectData = function (value, metas, cache) {
        if (!value) {
            value = {};
        }
        if (!cache) {
            cache = {};
        }
        if (metas && metas.length > 0) {
            for (i = 0; i < metas.length; i++) {
                var metaObj = TempoMineMetaUtils.convertMetaToObj(metas[i]);
                if (metaObj.type && metaObj.type != "") {
                    value[metaObj.desc] = metaObj.desc;
                    cache[metaObj.desc] = metaObj.type;
                }
            }
        }
    }

    /**
     * 若数据中的列名是以向量的前缀开头的，则需要去掉该前缀，重新命名
     * 包括metadata中的Attribute
     */
    TempoMineMetaUtils.renameVectorWithMeta = function (meta) {
        if (meta && meta.length) {
            for (var i in meta) {
                if (meta[i] && meta[i].length > 2 && meta[i][0]
                    && meta[i][0].toUpperCase().indexOf('TEMPOV_') == 0) {
                    console.log("find vector column: " + meta[i]);
                    meta[i][0] = meta[i][0].substr(7);
                }
            }
        }
        return meta;
    }

    /**
     * 信号meta的共同方法
     *
     */
    TempoMineMetaUtils.signalMeta = function () {
        var signalMeta = [];
        var fileName = {"name": "名称", "desc": "名称", "type": "STRING", "role": "regular"}
        var startTime = {"name": "起始时间", "desc": "起始时间", "type": "TIMESTAMP", "role": "regular"}
        var sampleRate = {"name": "采样率", "desc": "采样率", "type": "FLOAT", "role": "regular"}
        var signalData = {"name": "信号数据", "desc": "信号数据", "type": "ARRAY", "role": "regular"}
        var signalLength = {"name": "信号长度", "desc": "信号长度", "type": "INT", "role": "regular"}
        signalMeta.push(TempoMineMetaUtils.convertObjToMetaOne(fileName));
        signalMeta.push(TempoMineMetaUtils.convertObjToMetaOne(startTime));
        signalMeta.push(TempoMineMetaUtils.convertObjToMetaOne(sampleRate));
        signalMeta.push(TempoMineMetaUtils.convertObjToMetaOne(signalData));
        signalMeta.push(TempoMineMetaUtils.convertObjToMetaOne(signalLength));
        return signalMeta;
    }

    /**
     * 去掉不参与计算角色的元信息
     * @autor liuhs
     * @since 2017-04-07
     * @param metadata
     * 			元信息
     * @return 返回不含不参与计算角色的元信息
     */
    TempoMineMetaUtils.extractRoleMetadata = function(metaData, role) {

        var metadata = TempoUtils.clone(metaData);
        var metadataWithCal = [];
        if (metadata.length > 0) {
            for (var j = 0; j < metadata.length;j++) {
                var item = TempoMineMetaUtils.convertMetaToObj(metadata[j]);
                if (role == item.role) {
                    if (TempoMineMetaUtils.isNumber(item.type)) {
                        metadata[j][2] = "NUMBER";
                    }
                    var metadatam = [metadata[j][0], metadata[j][2],metadata[j][3]];
                    metadataWithCal.push(metadatam.join());
                }
            }
        }
        return metadataWithCal;
    }

    /**
     * 对模型元信息和要处理的数据取交集
     * @autor lirm
     * @since 2021-11-05
     * @param algMetaDataWithCal
     * 			模型端口元信息
     * 		  datasetMetaDataWithCal
     * 			数据集端口元信息
     * @return 包含交集项的集合
     */
    TempoMineMetaUtils.intersectionMetadata = function (algMetaDataWithCal, datasetMetaDataWithCal) {
        //临时数组存放
        var tempArray = [];
        //存放两个元信息交集的集合
        var intersectionArray = [];
        for (var i = 0; i < algMetaDataWithCal.length; i++) {
            //将algMetaDataWithCal中的元素值作为tempArray中的键，值为true；
            tempArray[algMetaDataWithCal[i]] = true;
        }
        for (var i = 0; i < datasetMetaDataWithCal.length; i++) {
            if (tempArray[datasetMetaDataWithCal[i]]) {
                //过滤datasetMetaDataWithCal中与algMetaDataWithCal相同的元素
                intersectionArray.push(datasetMetaDataWithCal[i]);
            }
        }
        return intersectionArray;
    }
    /**
     * 使用字段名+注释名+类型+ID列判断字段状态是否发生改变
     *
     *1.如果用户已选择元信息中包含已加载中没有的列信息，则返回该列的具体对象列表和比对错误原因
     * 返回的数组中对象的结构1： {"meta":choosedMetaI,"reason":"name"} 已选择列在待选项中未发现。
     * 返回的数组中对象的结构2：{"meta":choosedMetaI,"reason":"type"} 已选择列的类型和待选项中不匹配。
     * 返回的数组中对象的结构2：{"meta":choosedMetaI,"reason":"more"} 待选项数据增加。
     * 返回的数组中对象的结构3：{"meta":choosedMetaI,"reason":"idColumn"} 向量自回归右侧已选择字段被设置为ID列
     * @param preparedMeta  输入端口数据
     * @param choosedMeta   向量自回归右侧数据
     * @param returnObjType 需要返回的错误对象集合的类型"array"：数组，"map"：代表map结构。默认值:"array"<br>
     *            如果返回为map，则key为name属性。
     * @param needValidLengthSame
     *          是否需要校验传入的两个数组的长度相同，默认不校验
     */

    TempoMineMetaUtils.checkVectorAutoRegression=function (preparedMeta, choosedMeta, returnObjType, needValidLengthSame) {
        debugger;
        var rTypeArray = "array";
        var rTypeMap = "map";
        // 设置返回类型的默认值
        if (!returnObjType) {
            returnObjType = rTypeArray;
        }
        // 参数检查
        if (!(returnObjType == rTypeArray || returnObjType == rTypeMap)) {
            console.log("TempoMineMetaUtils.checkMeta: param returnObjType value error!Must be \"" + rTypeArray + "\" or \"" + rTypeMap + "\"");
        }
        //保存需要返回的数据
        var rErrorMetas = [];
        if (returnObjType == rTypeMap) {
            rErrorMetas = TempoMineUtils.hashMap();
        }
        //右侧树判空
        if (!choosedMeta) {
            console.log("TempoMineMetaUtils.checkMeta->choosedMeta is :"
                + choosedMeta);
            return rErrorMetas;
        }
        //输入端口数据判空
        if (!preparedMeta) {
            console.log("TempoMineMetaUtils.checkMeta->preparedMeta is :"
                + preparedMeta);
            return rErrorMetas;
        }
        // 长度不一致(长度校验)
        if (needValidLengthSame && preparedMeta.length != choosedMeta.length) {
            var errorObj = {
                "meta": [],
                "reason": "more"
            }
            if (returnObjType == rTypeArray) {
                rErrorMetas.push(errorObj);
            } else {
                rErrorMetas.put("", errorObj);
            }
            return rErrorMetas;
        }
        //将输入端口数据设置为key=名称
        var preparedMetaMap = TempoMineUtils.hashMap();
        for (var i = 0; i < preparedMeta.length; i++) {
            var meta = preparedMeta[i];
            var metaObj = TempoMineMetaUtils.convertMetaToObj(meta);
            preparedMetaMap.put(metaObj.desc, metaObj);
        }

        //判断向量自回归右侧数据是否发生改变或者被设置为ID列
        for (var i = 0; i < choosedMeta.length; i++) {
            //保存右侧树数据
            var choosedMetaI = choosedMeta[i];
            //将右侧数据的key设置为名称+别名+类型的格式
            var keyN = choosedMetaI.desc;
            //保存类型
            var cmType = choosedMetaI.type;
            //判断能否根据keyN从输入端口数据获取数据
            var preparedMeata = preparedMetaMap.get(keyN);
            var errorMetaObj = {// 默认是名称错误
                "meta": choosedMetaI,
                "reason": "name"
            };
            //能获取数据
            if (preparedMeata) {
                //判断右侧树字段类型和输入端口字段类型是否相同
                var isTypeEqual = TempoMineMetaUtils.typeEquals(cmType, preparedMeata.type);
                //类型不同
                if (!isTypeEqual) {
                    errorMetaObj.reason = "type";
                    if (returnObjType == rTypeArray) {
                        rErrorMetas.push(errorMetaObj);
                    } else {
                        rErrorMetas.put(errorMetaObj.meta.desc, errorMetaObj);
                    }
                }
                //判断判断右侧树字段类型和输入端口注释名是否相同
                var isNameEqual = TempoMineMetaUtils.nameEquals(preparedMeata.name, choosedMetaI.name);
                //注释名不同
                if (!isNameEqual) {
                    if (returnObjType == rTypeArray) {
                        rErrorMetas.push(errorMetaObj);
                    } else {
                        rErrorMetas.put(errorMetaObj.meta.desc, errorMetaObj);
                    }
                }
                //判读右侧树字段是否是ID列
                if(preparedMeata.role==window.constant.MINE_DATA_ROLE.ID){
                    errorMetaObj.reason = "idColumn";
                    if (returnObjType == rTypeArray) {
                        rErrorMetas.push(errorMetaObj);
                    } else {
                        rErrorMetas.put(errorMetaObj.meta.desc, errorMetaObj);
                    }
                }
            }
            //preparedMeata为undefined默认是名称错误
            if (!preparedMeata || errorMetaObj.reason == "type") {
                if (returnObjType == rTypeArray) {
                    rErrorMetas.push(errorMetaObj);
                } else {
                    rErrorMetas.put(errorMetaObj.meta.desc, errorMetaObj);
                }
            }
        }
        return rErrorMetas;
    }

})(jQuery);